package com.file.parser;

import com.file.bo.ResponseData;
import com.file.bo.mail.CITIC;
import com.file.bo.mail.CITICTran;
import com.file.constant.EfpConstants;
import com.file.constant.ErrorCode;
import com.file.parser.traprange.PDFTableExtractor;
import com.file.util.JsonUtils;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class CITICPdfParser extends BasePdfParser {

	public ResponseData<String> parseCITICPdfToJson(String filePath) {
		log.info("parseCITICPdfToJson started, filePath:{}", filePath);
		String json = null;

		try {
			CITIC icbc = parseCITICPdf(filePath);
			json = JsonUtils.convertObjectToJson(icbc);
		} catch (Exception e) {
			log.error("[OnError]parseCITICPdfToJson failed, filePath:{}", filePath, e);
			return new ResponseData<String>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(),
					ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
		}

		log.info("parseCITICPdfToJson completed, filePath:{}", filePath);
		return new ResponseData<String>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
	}

	private CITIC parseCITICPdf(String filePath) {
		CITIC citic = parseCITICHeader(filePath);
		List<CITICTran> citicTrans = parseCITICTrans(filePath);
		try {
			citicTrans = parseRecipient(filePath, citicTrans);
		} catch (Exception e) {
			log.warn("parseRecipient failed", e);
		}
		citic.setCiticTrans(citicTrans);
		log.info("citic = " + citic);
		return citic;
	}

	private CITIC parseCITICHeader(String filePath) {
		CITIC citic = new CITIC();
		String pdfHeaderText = parsePdfHeaderText(filePath);
		String accountName = pdfHeaderText.substring(pdfHeaderText.indexOf("户名：") + 3, pdfHeaderText.indexOf("证件类型"))
				.trim();
		String idType = pdfHeaderText.substring(pdfHeaderText.indexOf("证件类型：") + 5, pdfHeaderText.indexOf("证件号码"))
				.trim();
		String idNumber = pdfHeaderText
				.substring(pdfHeaderText.indexOf("证件号码：") + 5, pdfHeaderText.indexOf("Account name")).trim();
		String accountNo = pdfHeaderText.substring(pdfHeaderText.indexOf("账号：") + 3, pdfHeaderText.indexOf("时间段"))
				.trim();
		String inquiryPeriod = pdfHeaderText.substring(pdfHeaderText.indexOf("时间段：") + 4, pdfHeaderText.indexOf("开立日期"))
				.trim();
		String issuanceDate = pdfHeaderText
				.substring(pdfHeaderText.indexOf("开立日期：") + 5, pdfHeaderText.indexOf("Account number")).trim();
		String inquireTheMinimumLimit = pdfHeaderText
				.substring(pdfHeaderText.indexOf("查询最低限额：") + 7, pdfHeaderText.indexOf("币种")).trim();
		String currency = pdfHeaderText
				.substring(pdfHeaderText.indexOf("币种：") + 3, pdfHeaderText.indexOf("Inquire the minimum limit")).trim();
		citic.setAccountName(accountName);
		citic.setIdType(idType);
		citic.setIdNumber(idNumber);
		citic.setAccountNo(accountNo);
		citic.setInquiryPeriod(inquiryPeriod);
		citic.setIssuanceDate(issuanceDate);
		citic.setInquireTheMinimumLimit(inquireTheMinimumLimit);
		citic.setCurrency(currency);

		return citic;
	}

	private List<CITICTran> parseCITICTrans(String filePath) {
		List<CITICTran> citicTrans = new ArrayList<>();

		String transText = parseTransToText(filePath);
		if (Strings.isNullOrEmpty(transText)) {
			return citicTrans;
		}

		List<List<String>> tranFieldsList = parseTransTextToTranFieldsList(transText);

		for (List<String> strings : tranFieldsList) {
			if (StringUtils.isNotBlank(strings.get(0))) {
				CITICTran citicTran = new CITICTran();
				citicTran.setTransactionDate(strings.get(0));
				citicTran.setAccountReceivable(strings.get(1));
				citicTran.setAccountPaid(strings.get(2));
				citicTran.setAccountBalance(strings.get(3));
				citicTran.setDescription(strings.get(4));
				citicTrans.add(citicTran);
			}
		}

		return citicTrans;
	}

	private String parseTransToText(String filePath) {
		PDFTableExtractor extractor = (new PDFTableExtractor()).setSource(filePath);
		int pdfPageNumber = getPdfPageNumber(filePath);
		// 去掉第一页的Header，
		int[] skipFirstPageHeaderLinesIndexes = new int[EfpConstants.CITIC_PDF_HEADER_LINE_NUMBER];
		for (int i = 0; i < EfpConstants.CITIC_PDF_HEADER_LINE_NUMBER; i++) {
			skipFirstPageHeaderLinesIndexes[i] = i;
		}
		extractor.exceptLine(0, skipFirstPageHeaderLinesIndexes);

		// 处理从第二页到最后一页的header
		for (int i = 1; i < pdfPageNumber; i++) {
			int[] skipLinesInNoneFirstPage = { 0, 1, 2, 3 };
			extractor.exceptLine(i, skipLinesInNoneFirstPage);
		}

		// 去掉最后一页的Footer,两种情况
		int lineNumberInLastPdf = getLineNumberInLastPage(filePath, pdfPageNumber);
		// 1.footer文本行完整展现在最后一页PDF,则直接排除最后一页的footer文本行
		if (lineNumberInLastPdf >= EfpConstants.CITIC_PDF_FOOTER_LINE_NUMBER) {
			int[] skipLastPageFooterLinesIndexes = new int[EfpConstants.CITIC_PDF_FOOTER_LINE_NUMBER];
			for (int j = 0; j < EfpConstants.CITIC_PDF_FOOTER_LINE_NUMBER; j++) {
				skipLastPageFooterLinesIndexes[j] = -(j + 1);
			}
			extractor.exceptLine(pdfPageNumber - 1, skipLastPageFooterLinesIndexes);
		} else {
			// 2.footer文本行拆分在倒数第一页和倒数第二页，则直接排除最后一页和倒数第二页的WECHAT_FOOTER_LINE_NO-lineNumberInLastPdf
			extractor.exceptPage(pdfPageNumber - 1);

			int footerLinesNumberInlastSecondPage = EfpConstants.CITIC_PDF_FOOTER_LINE_NUMBER - lineNumberInLastPdf;
			int[] skipLastSecondPageFooterLinesIndexes = new int[footerLinesNumberInlastSecondPage];
			for (int k = 0; k < footerLinesNumberInlastSecondPage; k++) {
				skipLastSecondPageFooterLinesIndexes[k] = -(k + 1);
			}
			extractor.exceptLine(pdfPageNumber - 2, skipLastSecondPageFooterLinesIndexes);
		}

		String text = extractPdfToText(extractor);
		return text;
	}

	public List<CITICTran> parseRecipient(String filePath, List<CITICTran> citicTrans) {
		String pdfText = getPdfTextByStripper(filePath);
		pdfText = pdfText.replace(System.getProperty("line.separator", "\n"), " ");

		// 此处一行的格式2021-09-01 RMB 650.00 RMB 6.30
		Pattern pattern1 = Pattern
				.compile("\\d{4}-\\d{2}-\\d{2}\\s\\S{1,5}\\s\\d{1,9}.\\d{2}\\s\\S{1,5}\\s\\d{1,9}.\\d{2}");
		Matcher matcher1 = pattern1.matcher(pdfText);

		// 每行交易记录的第一个字所在的index
		int tranIndex = 0;
		Map<Integer, Integer> tranTextStartIndexMap = new HashMap<>();

		while (matcher1.find()) {
			// log.info(
			// 		"Match \"" + matcher1.group() + "\" at positions " + matcher1.start() + "-" + (matcher1.end() - 1));
			tranTextStartIndexMap.put(tranIndex, matcher1.start());
			tranIndex++;
		}

		// 找出每行交易记录的文本
		List<String> tranTextList = new ArrayList<>();
		for (int i = 1; i < tranTextStartIndexMap.size(); i++) {
			String tranText = pdfText.substring(tranTextStartIndexMap.get(i - 1), tranTextStartIndexMap.get(i));
			if (tranText.contains("交易日期")) {
				tranText = tranText.substring(0, tranText.indexOf("/") - 4).trim();
			}
			// log.info(tranText);
			tranTextList.add(tranText);
		}

		String lastTranText = pdfText.substring(tranTextStartIndexMap.get(tranTextStartIndexMap.size() - 1));
		lastTranText = lastTranText.substring(0, lastTranText.indexOf("声明：")).trim();
		tranTextList.add(lastTranText);

		// 找出每行交易里的对手信息的值
		// 此处一行除去对手户名的格式 2021-09-14 RMB 50.00 RMB 52.15 支付宝
		Pattern pattern2 = Pattern
				.compile("\\d{4}-\\d{2}-\\d{2}\\s\\S{1,5}\\s\\d{1,9}.\\d{2}\\s\\S{1,5}\\s\\d{1,9}.\\d{2}\\s\\S{0,20}");
		for (int i = 0; i < citicTrans.size(); i++) {
			Matcher matcher2 = pattern2.matcher(tranTextList.get(i));
			while (matcher2.find()) {
				String recipient = tranTextList.get(i).substring(matcher2.end()).trim();
				citicTrans.get(i).setRecipient(recipient.replace(" ", ""));
			}
		}

		return citicTrans;
	}

	public static void main(String[] args) {
		CITICPdfParser citicPdfParser = new CITICPdfParser();
		CITIC citic = citicPdfParser.parseCITICPdf("E:\\data\\files\\CITIC\\中信银行交易明细.pdf");
		String json = JsonUtils.convertObjectToJson(citic);
		System.out.println(json);
	}

}
